// ts 泛型

// 泛型接口
interface GenericIdentityFn<T> {
  (arg: T): T;
}

// 泛型类
class GenericNumber<T> {
  zeroValue!: T;
  add!: (x: T, y: T) => T;
}

let myGenricNumber = new GenericNumber<number>();
myGenricNumber.zeroValue = 0;
myGenricNumber.add = function (x, y) {
  return x + y;
};

/**
 ** 常见的泛型变量
 *T（Type）：表示一个 TypeScript 类型
 *K（Key）：表示对象中的键类型
 *V（Value）：表示对象中的值类型
 *E（Element）：表示元素类型
 */

//  泛型工具类型

interface person {
  name: string;
  age: number;
}

// typeof
const xuzy: person = { name: "xuzy", age: 30 };

type Xuzy = typeof xuzy; // => person

function toArray(x: number): Array<number> {
  return [x];
}

type Func = typeof toArray; // => (x: number) => Array<number>

// keyof
type k1 = keyof person; //'name'|'age'
type k2 = keyof person[]; // "length" | "toString" | "pop" | "push" | "concat" | "join"
type k3 = keyof { [x: string]: person }; //'string' | 'number'

// in
type Keys = "a" | "b" | "c";
type Obj = {
  [p in Keys]: any;
}; // -> { a: any, b: any, c: any }

// infer
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
// 以上代码中 infer R 就是声明一个变量来承载传入函数签名的返回值类型，简单说就是用它取到函数返回值的类型方便之后使用

// extends
function loggingPerson<T extends person>(arg: T) {
  return arg;
}

// Partial
type Partial<T> = {
  [P in keyof T]?: T[P];
};
// Partial<T> 的作用就是将某个类型里的属性全部变为可选项 ?。

// example
interface Todo {
  title: string;
  description: string;
}

function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  return { ...todo, ...fieldsToUpdate };
}

const todo1 = {
  title: "ooooo",
  description: "wwwww",
};

const todo2 = updateTodo(todo1, {
  description: "throw",
});

console.log(todo2);

export {};
